import wx

from event_bus import EventBus
from models import db_proxy, Sample
from uis import CategoryEdit
from utils import switch
from view_models import project_state
from wxutils import call_after


class CategoryManage(CategoryEdit):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.Bind(wx.EVT_RADIOBUTTON, self.activate_edit, self.add_mark)
        self.Bind(wx.EVT_RADIOBUTTON, self.activate_edit, self.rename_mark)
        self.Bind(wx.EVT_RADIOBUTTON, self.activate_edit, self.delete_mark)
        self.Bind(wx.EVT_BUTTON, self.do_operate, self.execute_operation)

        EventBus().register_topic(topic="switched_to_category", handler=self.update_categories)
        EventBus().register_topic(topic="categories_updated", handler=self.update_categories)

    @call_after
    def update_categories(self, _):
        self.add_mark.SetValue(False)
        self.add_mark_name.Clear()
        self.add_mark_name.Disable()
        self.rename_mark.SetValue(False)
        self.new_mark_name.Clear()
        self.new_mark_name.Disable()
        self.delete_mark.SetValue(False)
        self.mark_list.SetItems(sorted([item for item in project_state.categories]))

    def activate_edit(self, event: wx.CommandEvent):
        for case in switch(event.GetEventObject()):
            if case(self.add_mark):
                self.add_mark_name.Enable()
                self.new_mark_name.Disable()
            if case(self.rename_mark):
                self.add_mark_name.Disable()
                self.new_mark_name.Enable()
            if case(self.delete_mark):
                self.add_mark_name.Disable()
                self.new_mark_name.Disable()

    def force_delete(self, target):
        confirm = wx.MessageBox(f"确定要删除特征 {target} 吗？这会导致所有使用该特征的样本丢失此特征，"
                                f"并且没有任何特征的样本将会被删除！",
                                "特征删除",
                                wx.YES_NO | wx.ICON_WARNING,
                                self)
        if confirm == wx.YES:
            with db_proxy.atomic():
                for sample in Sample.select().iterator():
                    if target in sample.categories:
                        sample.categories.remove(target)
                        if len(sample.categories) == 0:
                            sample.delete_instance()
                        else:
                            sample.save()
            project_state.current.categories.remove(target)
            project_state.refresh_categories()
            EventBus().post_topic(topic="categories_updated", event=None)
            wx.MessageBox(f"指定特征 {target} 已经完全删除，相关无效样本也已经清理完毕。", "删除结束", wx.OK, self)

    def rename_category(self, old_mark, new_mark):
        confirm = wx.MessageBox(f"确定要将特征 {old_mark} 替换为 {new_mark} 吗？",
                                "特征替换",
                                wx.YES_NO | wx.ICON_QUESTION,
                                self)
        if confirm == wx.YES:
            with db_proxy.atomic():
                for sample in Sample.select().iterator():
                    if old_mark in sample.categories:
                        sample.categories.remove(old_mark)
                        sample.categories.append(new_mark)
                        sample.save()
            project_state.current.categories.remove(old_mark)
            project_state.refresh_categories()
            EventBus().post_topic(topic="categories_updated", event=None)
            wx.MessageBox(f"指定特征 {old_mark} 已经完全由 {new_mark} 替换。", "替换结束", wx.OK, self)

    @staticmethod
    def add_category(target):
        project_state.current.categories.add(target)
        project_state.refresh_categories()
        EventBus().post_topic(topic="categories_updated", event=None)

    def do_operate(self, _):
        if self.add_mark.GetValue():
            self.add_category(self.add_mark_name.GetValue())
        elif self.rename_mark.GetValue():
            self.rename_category(self.mark_list.GetStringSelection(), self.new_mark_name.GetValue())
        elif self.delete_mark.GetValue():
            self.force_delete(self.mark_list.GetStringSelection())




